from typing import Callable, Dict, List, Type
import weakref
from src.events import Event


class EventBus:
    """事件总线"""
    
    def __init__(self):
        self._listeners: Dict[Type[Event], List[Callable]] = {}
        self._temporary_listeners: Dict[Type[Event], List[Callable]] = {}
        
    def subscribe(self, event_type: Type[Event], listener: Callable, temporary: bool = False):
        """订阅事件
        
        Args:
            event_type: 事件类型
            listener: 事件监听器
            temporary: 是否为临时监听器（只处理一次事件后自动取消订阅）
        """
        listeners_dict = self._temporary_listeners if temporary else self._listeners
        
        if event_type not in listeners_dict:
            listeners_dict[event_type] = []
        listeners_dict[event_type].append(listener)
        
    def unsubscribe(self, event_type: Type[Event], listener: Callable):
        """取消订阅事件"""
        # 从永久监听器中移除
        if event_type in self._listeners:
            try:
                self._listeners[event_type].remove(listener)
            except ValueError:
                pass
                
        # 从临时监听器中移除
        if event_type in self._temporary_listeners:
            try:
                self._temporary_listeners[event_type].remove(listener)
            except ValueError:
                pass
                
    def publish(self, event: Event):
        """发布事件"""
        event_type = type(event)
        
        # 处理永久监听器
        if event_type in self._listeners:
            for listener in self._listeners[event_type][:]:  # 使用副本防止在迭代时修改列表
                try:
                    listener(event)
                except Exception as e:
                    print(f"处理事件 {event_type.__name__} 时发生错误: {e}")
        
        # 处理临时监听器
        if event_type in self._temporary_listeners:
            for listener in self._temporary_listeners[event_type][:]:
                try:
                    listener(event)
                except Exception as e:
                    print(f"处理事件 {event_type.__name__} 时发生错误: {e}")
            # 清空临时监听器
            self._temporary_listeners[event_type].clear()
            
    def clear(self):
        """清空所有监听器"""
        self._listeners.clear()
        self._temporary_listeners.clear()